package com.yunyouyi.cpicture.application.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunyouyi.cpicture.interfaces.dto.space.analyze.*;
import com.yunyouyi.cpicture.infrastructure.exception.BusinessException;
import com.yunyouyi.cpicture.infrastructure.exception.ErrorCode;
import com.yunyouyi.cpicture.infrastructure.exception.ThrowUtils;
import com.yunyouyi.cpicture.domain.picture.entity.Picture;
import com.yunyouyi.cpicture.interfaces.vo.space.analyze.*;
import com.yunyouyi.cpicture.domain.space.entity.Space;
import com.yunyouyi.cpicture.domain.user.entity.User;
import com.yunyouyi.cpicture.application.service.PictureApplicationService;
import com.yunyouyi.cpicture.application.service.SpaceAnalyzeApplicationService;
import com.yunyouyi.cpicture.application.service.SpaceApplicationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SpaceAnalyzeApplicationServiceImpl implements SpaceAnalyzeApplicationService {

    @Resource
    SpaceApplicationService spaceApplicationService;

    @Resource
    private PictureApplicationService pictureApplicationService;


    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeDTO spaceUsageAnalyzeDTO, User loginUser){
        ThrowUtils.throwIf(spaceUsageAnalyzeDTO == null, ErrorCode.PARAMS_ERROR, "参数不能为空");
        if(spaceUsageAnalyzeDTO.isQueryPublic() || spaceUsageAnalyzeDTO.isQueryAll()){
            //查询全部或者公共图库逻辑
            //仅管理员可以查询
            boolean isAdmin = loginUser.isAdmin();
            ThrowUtils.throwIf(!isAdmin, ErrorCode.NO_AUTH_ERROR, "无权限访问空间");
            //统计公共图库的资源使用
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("picSize");
            if(!spaceUsageAnalyzeDTO.isQueryAll()){
                queryWrapper.isNull("spaceId");
            }
            List<Object> pictureObjects = pictureApplicationService.getBaseMapper().selectObjs(queryWrapper);
            long usedSize = pictureObjects.stream().mapToLong(result -> result instanceof Long ? (Long) result : 0).sum();
            long usedCount = pictureObjects.size();
            //封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(usedSize);
            spaceUsageAnalyzeResponse.setUsedCount(usedCount);
            //公共图库无上限无比例
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResponse.setCountUsageRatio(null);
            return spaceUsageAnalyzeResponse;
        }else{
            //查询指定空间
            Long spaceId = spaceUsageAnalyzeDTO.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCode.PARAMS_ERROR);
            Space space = spaceApplicationService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "空间不存在");
            //权限校验空间所有者和管理可访问
            spaceApplicationService.checkSpaceAuth(loginUser, space);
            //构造返回结果
            SpaceUsageAnalyzeResponse response = new SpaceUsageAnalyzeResponse();
            response.setUsedSize(space.getTotalSize());
            response.setUsedCount(space.getTotalCount());
            response.setMaxSize(space.getMaxSize());
            response.setMaxCount(space.getMaxCount());
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize()*100.0/space.getMaxSize(), 2).doubleValue();
            response.setSizeUsageRatio(sizeUsageRatio);
            double countUsageRatio = NumberUtil.round(space.getTotalCount()*100.0/space.getMaxCount(), 2).doubleValue();
            response.setCountUsageRatio(countUsageRatio);
            return response;
        }
    }

    /**
     * 获取空间分类分析结果
     * @param spaceCategoryAnalyzeDTO
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyzeResponse(SpaceCategoryAnalyzeDTO spaceCategoryAnalyzeDTO, User loginUser){
        ThrowUtils.throwIf(spaceCategoryAnalyzeDTO == null, ErrorCode.PARAMS_ERROR, "参数不能为空");
        checkAnalyzeAuth(spaceCategoryAnalyzeDTO, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //根据分析范围补充查询条件
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeDTO, queryWrapper);

        //分组查询
        queryWrapper.select("category as category,COUNT(*) as count,SUM(picSize) as totalSize").groupBy("category");

        return pictureApplicationService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(result -> {
                    // 更健壮的写法示例
                    String category = Optional.ofNullable(result.get("category"))
                            .map(Object::toString)
                            .orElse("未分类");
                    Number countNumber = (Number) result.get("count"); // 先做类型检查会更好
                    Long count = (countNumber != null) ? countNumber.longValue() : 0L;
                    // 安全转换写法（带空值检查）
                    Number totalSizeNum = (Number) result.get("totalSize");
                    Long totalSize = totalSizeNum != null ? totalSizeNum.longValue() : 0L;
                    return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
                }).collect(Collectors.toList());
    }

    /**
     * 获取空间标签分析结果
     * @param spaceAnalyzeDTO
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceTagAnalyzeResponse>  getSpaceTagAnalyzeDTO(SpaceTagAnalyzeDTO spaceAnalyzeDTO, User loginUser){
        ThrowUtils.throwIf(spaceAnalyzeDTO == null, ErrorCode.PARAMS_ERROR, "分析参数不能为空");
        checkAnalyzeAuth(spaceAnalyzeDTO, loginUser);
        //构造查询参数
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceAnalyzeDTO, queryWrapper);
        queryWrapper.select("tags");
        //查询
        List<String> tags = pictureApplicationService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .filter(ObjUtil::isNotNull)
                .map(Object::toString)
                .collect(Collectors.toList());
        log.info("analyze tags列表:{}", tags);
        //计数
        Map<String, Long> collect = tags.stream()
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));
        log.info("analyze tags扁平后列表:{}", collect);
        return collect.entrySet().stream()
                .sorted((e1,e2)->Long.compare(e2.getValue(), e1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }
    /**
     * 获取空间用户分析结果
     * @param spaceUserAnalyzeDTO
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyzeResponse(SpaceUserAnalyzeDTO spaceUserAnalyzeDTO, User loginUser){
        ThrowUtils.throwIf(spaceUserAnalyzeDTO == null, ErrorCode.PARAMS_ERROR, "分析参数不能为空");
        checkAnalyzeAuth(spaceUserAnalyzeDTO, loginUser);
        //构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //自动填充查询条件
        Long userId = spaceUserAnalyzeDTO.getUserId();
        queryWrapper.eq(ObjUtil.isNotNull(userId),"userId", userId);
        //当spaceId不为空
        if (spaceUserAnalyzeDTO.getSpaceId() != null) {
            QueryWrapper<Space> spaceQueryWrapper = new QueryWrapper<>();
            spaceQueryWrapper.select("id");
            spaceQueryWrapper.eq("userId", userId);
            Space space = spaceApplicationService.getBaseMapper().selectOne(spaceQueryWrapper);
            if (space != null) {
                spaceUserAnalyzeDTO.setSpaceId(space.getId());
            }
        }
        fillAnalyzeQueryWrapper(spaceUserAnalyzeDTO, queryWrapper);

        switch(spaceUserAnalyzeDTO.getTimeDimension()){
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as period", "COUNT(*) as count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) as period", "COUNT(*) as count");
                break;
            case "month":
                queryWrapper.select("MONTH(createTime) as period", "COUNT(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"时间维度错误");
        }
        queryWrapper.groupBy("period").orderByAsc("period");
        //查询结果
        List<Map<String, Object>> queryResult = pictureApplicationService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream().map(result -> {
            String period = result.get("period").toString();
            Long count = ((Number) result.get("count")).longValue();
            return new SpaceUserAnalyzeResponse(period, count);
        }).collect(Collectors.toList());
    }

    /**
     * 获取空间排行分析结果
     * @param spaceRankAnalyzeDTO
     * @param loginUser
     * @return
     */
    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeDTO spaceRankAnalyzeDTO, User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeDTO == null, ErrorCode.PARAMS_ERROR);

        // 仅管理员可查看空间排行
        ThrowUtils.throwIf(!loginUser.isAdmin(), ErrorCode.NO_AUTH_ERROR, "无权查看空间排行");

        // 构造查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "spaceName", "userId", "totalSize")
                .orderByDesc("totalSize")
                .last("LIMIT " + spaceRankAnalyzeDTO.getTopN()); // 取前 N 名

        // 查询结果
        return spaceApplicationService.list(queryWrapper);
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeDTO spaceSizeAnalyzeDTO, User loginUser) {
        ThrowUtils.throwIf(spaceSizeAnalyzeDTO == null, ErrorCode.PARAMS_ERROR);

        // 检查权限
        checkAnalyzeAuth(spaceSizeAnalyzeDTO, loginUser);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeDTO, queryWrapper);

        // 查询所有符合条件的图片大小
        queryWrapper.select("picSize");
        List<Long> picSizes = pictureApplicationService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .map(size -> ((Number) size).longValue())
                .collect(Collectors.toList());

        // 定义分段范围，注意使用有序 Map
        Map<String, Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB", picSizes.stream().filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB", picSizes.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
        sizeRanges.put("500KB-1MB", picSizes.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB", picSizes.stream().filter(size -> size >= 1 * 1024 * 1024).count());

        // 转换为响应对象
        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 检查分析权限
     * @param spaceAnalyzeDTO
     * @param loginUser
     */
    private void checkAnalyzeAuth(SpaceAnalyzeDTO spaceAnalyzeDTO, User loginUser){
        if(spaceAnalyzeDTO.isQueryAll() || spaceAnalyzeDTO.isQueryPublic()){
            // 查询所有或者查询公开需要管理员权限
            ThrowUtils.throwIf(!loginUser.getUserRole().equals("admin"), ErrorCode.NO_AUTH_ERROR, "无权限");
        }else{
            Long spaceId = spaceAnalyzeDTO.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCode.PARAMS_ERROR);
            Space space = spaceApplicationService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "空间不存在");
            spaceApplicationService.checkSpaceAuth(loginUser, space);
        }
    }

    /**
     * 填充查询条件
     * @param spaceAnalyzeDTO
     * @param queryWrapper
     */
    private static void fillAnalyzeQueryWrapper(SpaceAnalyzeDTO spaceAnalyzeDTO, QueryWrapper<Picture> queryWrapper){
        if(spaceAnalyzeDTO.isQueryAll()){
            return;
        }
        if(spaceAnalyzeDTO.isQueryPublic()){
            queryWrapper.isNull("spaceId");
            return;
        }
        Long spaceId = spaceAnalyzeDTO.getSpaceId();
        if(spaceId != null){
            queryWrapper.eq("spaceId", spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "为指导查询范围");
    }

}
